/*
 *   Copyright 2012-present OSBI Ltd
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

// Packages
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { isEmpty, isNull } from 'lodash';
import isEqual from 'react-fast-compare';
import mouseTrap from 'react-mousetrap';
import ReduxBlockUi from 'react-block-ui/lib/redux';
import Fullscreen from 'react-full-screen';
import { Button } from '@blueprintjs/core';

// Actions
import { actionCreators } from '../../../actions';

// Layout
import Container from '../../Layout/Container';

// Elements
import {
  BannerUpgradeLicense,
  WorkspaceEmpty,
  WorkspaceFooter,
  WorkspaceResults,
  WorkspaceToolbar
} from '../../Elements';

// Alerts
import ResetQueryAlert from '../../Alerts/ResetQueryAlert';

// Dialogs
import {
  OpenQueryDialog,
  QueryDesignerDialog,
  SaveQueryDialog
} from '../../Dialogs';

// Utils
import {
  REQUEST_START,
  REQUEST_SUCCESS,
  REQUEST_FAILURE
} from '../../../utils/constants';

// Styles
import './Workspace.css';

class Workspace extends Component {
  state = {
    isOpenQueryDialog: false,
    isOpenSaveQueryDialog: false,
    isOpenResetQueryAlert: false,
    isOpenQueryDesignerDialog: false,
    isFullscreen: false
  };

  componentWillMount() {
    this.props.bindShortcut('mod+o', () => {
      this.handleOpenQueryDialog();

      return false;
    });

    this.handleBindShortcuts(this.props);
  }

  shouldComponentUpdate(nextProps, nextState) {
    return (
      !isEqual(this.props.licenseInfo, nextProps.licenseInfo) ||
      !isEqual(this.props.query, nextProps.query) ||
      !isEqual(this.props.queryResultset, nextProps.queryResultset) ||
      !isEqual(this.props.workspace, nextProps.workspace) ||
      !isEqual(this.props.blockUi, nextProps.blockUi) ||
      this.state.isOpenQueryDialog !== nextState.isOpenQueryDialog ||
      this.state.isOpenSaveQueryDialog !== nextState.isOpenSaveQueryDialog ||
      this.state.isOpenResetQueryAlert !== nextState.isOpenResetQueryAlert ||
      this.state.isOpenQueryDesignerDialog !==
        nextState.isOpenQueryDesignerDialog ||
      this.state.isFullscreen !== nextState.isFullscreen
    );
  }

  componentWillUpdate(nextProps, nextState) {
    this.handleBindShortcuts(nextProps);
  }

  handleBindShortcuts(props) {
    const { query, queryResultset, bindShortcut, unbindShortcut } = props;
    const { hasRun } = queryResultset;

    if (query && query.cube) {
      bindShortcut('mod+d', () => {
        this.handleQueryDesignerDialog();

        return false;
      });
    }

    if (hasRun) {
      bindShortcut('mod+s', () => {
        const { saveQueryAuto } = this.props;
        const file = this.getQueryFile();

        if (file) {
          saveQueryAuto(file);
        } else {
          this.handleSaveQueryDialog();
        }

        return false;
      });

      bindShortcut('mod+shift+s', () => {
        this.handleSaveQueryDialog();

        return false;
      });

      bindShortcut('mod+q', () => {
        this.handleResetQueryAlert();

        return false;
      });
    } else {
      unbindShortcut('mod+s');
      unbindShortcut('mod+q');
    }
  }

  hasResultset(resultset) {
    const { queryResultset } = resultset;

    return (
      resultset.hasRun &&
      !isEmpty(queryResultset) &&
      !isEmpty(queryResultset.cellset) &&
      isNull(queryResultset.error)
    );
  }

  getQueryFile() {
    const { workspace } = this.props.workspace;

    return workspace.file || null;
  }

  handleOpenQueryDialog = () => {
    this.setState(prevState => ({
      isOpenQueryDialog: !prevState.isOpenQueryDialog,
      isOpenSaveQueryDialog: false,
      isOpenResetQueryAlert: false,
      isOpenQueryDesignerDialog: false
    }));
  };

  handleSaveQueryDialog = () => {
    this.setState(prevState => ({
      isOpenQueryDialog: false,
      isOpenSaveQueryDialog: !prevState.isOpenSaveQueryDialog,
      isOpenResetQueryAlert: false,
      isOpenQueryDesignerDialog: false
    }));
  };

  handleResetQueryAlert = () => {
    this.setState(prevState => ({
      isOpenQueryDialog: false,
      isOpenSaveQueryDialog: false,
      isOpenResetQueryAlert: !prevState.isOpenResetQueryAlert,
      isOpenQueryDesignerDialog: false
    }));
  };

  handleQueryDesignerDialog = () => {
    this.setState(prevState => ({
      isOpenQueryDialog: false,
      isOpenSaveQueryDialog: false,
      isOpenResetQueryAlert: false,
      isOpenQueryDesignerDialog: !prevState.isOpenQueryDesignerDialog
    }));
  };

  handleRequestFullscreen = () => {
    this.setState(prevState => ({
      isFullscreen: !prevState.isFullscreen
    }));
  };

  render() {
    const {
      licenseInfo,
      query,
      queryResultset,
      workspace,
      blockUi
    } = this.props;
    const {
      isOpenQueryDialog,
      isOpenSaveQueryDialog,
      isOpenResetQueryAlert,
      isOpenQueryDesignerDialog,
      isFullscreen
    } = this.state;
    const hasResultset = this.hasResultset(queryResultset);

    return (
      <Container>
        <ReduxBlockUi
          tag="div"
          className="sku-workspace content-inner no-padding-top no-padding-right"
          block={REQUEST_START}
          unblock={[REQUEST_SUCCESS, REQUEST_FAILURE]}
          message={blockUi.message}
          loader={() => false}
          keepInView
        >
          <WorkspaceToolbar
            query={query}
            queryResultset={queryResultset}
            workspace={workspace}
            hasResultset={hasResultset}
            openQuery={this.handleOpenQueryDialog}
            saveQuery={this.handleSaveQueryDialog}
            resetQuery={this.handleResetQueryAlert}
            queryDesigner={this.handleQueryDesignerDialog}
            requestFullscreen={this.handleRequestFullscreen}
          />
          <BannerUpgradeLicense license={licenseInfo.license} />
          {queryResultset.hasRun ? (
            <Fullscreen
              enabled={isFullscreen}
              onChange={isFullscreen => this.setState({ isFullscreen })}
            >
              <WorkspaceResults
                isFullscreen={isFullscreen}
                hasResultset={hasResultset}
                queryResultset={queryResultset}
                workspace={workspace}
              />
              {isFullscreen && (
                <Button
                  className="sku-fullscreen-minimize"
                  icon="minimize"
                  large
                  minimal
                  onClick={this.handleRequestFullscreen}
                />
              )}
            </Fullscreen>
          ) : (
            <WorkspaceEmpty
              query={query}
              queryResultset={queryResultset}
              openQuery={this.handleOpenQueryDialog}
            />
          )}
          <WorkspaceFooter
            file={this.getQueryFile()}
            query={query}
            queryResultset={queryResultset}
          />
        </ReduxBlockUi>

        {isOpenQueryDialog && (
          <OpenQueryDialog onClose={this.handleOpenQueryDialog} />
        )}

        {isOpenSaveQueryDialog && (
          <SaveQueryDialog onClose={this.handleSaveQueryDialog} />
        )}

        {isOpenResetQueryAlert && (
          <ResetQueryAlert onCancel={this.handleResetQueryAlert} />
        )}

        {isOpenQueryDesignerDialog && (
          <QueryDesignerDialog onClose={this.handleQueryDesignerDialog} />
        )}
      </Container>
    );
  }
}

Workspace.propTypes = {
  licenseInfo: PropTypes.object.isRequired,
  query: PropTypes.object.isRequired,
  queryResultset: PropTypes.object.isRequired,
  workspace: PropTypes.object.isRequired,
  blockUi: PropTypes.object.isRequired,
  saveQueryAuto: PropTypes.func.isRequired
};

const mapStateToProps = state => ({
  licenseInfo: state.licenseInfo,
  ...state.query,
  queryResultset: state.queryResultset,
  workspace: state.workspace,
  blockUi: state.blockUi
});

const mapDispatchToProps = dispatch => ({
  saveQueryAuto: file => dispatch(actionCreators.saveQueryAuto(file))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(mouseTrap(Workspace));
